/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_components/zhiqim_console.htm
 *
 * Zhiqim Console is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.manager.presenter;

import org.zhiqim.httpd.HttpCookie;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.HttpResponse;
import org.zhiqim.httpd.context.ZmlContexts;
import org.zhiqim.httpd.util.Sessions;
import org.zhiqim.httpd.validate.ones.IsNotEmpty;
import org.zhiqim.httpd.validate.ones.IsNumericLen;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.model.codes.Base64;
import org.zhiqim.kernel.model.codes.RSA;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.ZmrBootstrap;
import org.zhiqim.manager.ZmrConstants;
import org.zhiqim.manager.ZmrPassworder;
import org.zhiqim.manager.ZmrSessionUser;
import org.zhiqim.manager.dbo.ZmrOperator;

/**
 * 登陆控制器
 *
 * @version v1.0.0 @author liuhu 2018-8-2 新建与整理
 */
@AnAlias("ZmrLoginPresenter")
public class ZmrLoginPresenter implements ZmrConstants
{
    public static void doLogin(HttpRequest request) throws Exception
    {
        ZmrOperator operator = ZmrBootstrap.getOperator();
        
        //1.判断传入参数
        request.addValidate(new IsNotEmpty("operatorCode", "用户账号不能为空"));
        request.addValidate(new IsNotEmpty("operatorPass", "用户密码不能为空"));
        
        boolean hasVerificationCode = operator.hasVerificationCode();
        if(hasVerificationCode){
            request.addValidate(new IsNumericLen("verificationCode", "验证码必须是4位数字", 4, 4));
        }
        if (!request.chkValidate())
        {
            request.setResponseError(request.getAlertMsg());
            return;
        }
        
        //2.验证码
        if(hasVerificationCode)
        {
            String verificationCode = request.getParameter("verificationCode");
            if(verificationCode.length() != 4)
            {
                request.setResponseError("验证码必须是4位数字");
                return;
            }
            String vcode = Sessions.getSessionVerificationCode(request);
            if (!verificationCode.equals(vcode))
            {
                request.setResponseError("验证码不正确或已失效，请新输入！");
                return;
            }
        }
        
        //3.验证操作员编码是否存在、是否停用，是否组停用
        String operatorCode = request.getParameter("operatorCode");
        if(!operatorCode.equals(operator.getOperatorCode()))
        {
            request.setResponseError("用户名不正确");
            return;
        }
        
        //4.验证密码
        String operatorPass = request.getParameter("operatorPass");
        
        byte[] operatorPassByte = Base64.decode(operatorPass);
        String privateKey = ZmrBootstrap.getPrivateKey();
        byte[] operatorPassDecrypt = RSA.decrypt(operatorPassByte, privateKey);
        operatorPass = new String(operatorPassDecrypt, _UTF_8_C_);
        
        boolean hasRememberCode = operator.hasRememberCode();
        boolean hasRememberPass = operator.hasRememberPass();
        
        if (isValidateRememberPass(operatorPass))
        {//全是●的密码表示记住密码要求验证密钥
            if (!hasRememberCode || !hasRememberPass || !operatorCode.equals(request.getCookie("operatorCode")))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
            
            ZmrPassworder passworder = ZmrBootstrap.getPassworder();
            String operatorPassSecr = request.getCookie("operatorPass");
            if (!passworder.secretChk(operatorCode, operatorPass, operator.getOperatorPassSalt(), operatorPassSecr))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        else
        {//正常验证密码
            if(!validatePassword(request, operator, operatorPass))
            {
                request.setResponseError("用户密码不正确");
                return;
            }
        }
        
        //5.完成验证，组装会话用户
        String welcomeUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_WELCOME));
        
        ZmrSessionUser sessionUser = new ZmrSessionUser(operator);
        sessionUser.setMainUrl(welcomeUrl);
        
        request.bindSessionUser(sessionUser);
        
        //6.判断需要保存信息到COOKIE
        if(hasRememberCode)
        {
            boolean rememberCode = request.getParameterBoolean("rememberCode");
            boolean rememberPass = request.getParameterBoolean("rememberPass");
            int day30 = 60*60*24*30;
            
            HttpResponse response = request.getResponse();
            if(rememberPass)
            {//勾选了记住密码，则一定记住登录名
                ZmrPassworder passworder = ZmrBootstrap.getPassworder();
                String operatorSecr = passworder.secret(operatorCode, operatorPass, operator.getOperatorPassSalt());
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", operatorSecr, day30));
            }
            else if (rememberCode)
            {//只记住用户名
                response.addCookie(new HttpCookie("operatorCode", operatorCode, day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
            else
            {//否则设置值为空
                response.addCookie(new HttpCookie("operatorCode", "", day30));
                response.addCookie(new HttpCookie("operatorPass", "", day30));
            }
        }
        
        //7.判断是否填写了主页跳转地址
        String defaultUrl = request.getRootPath(ZmlContexts.parseZmlContent(request, ZMR_MAIN_URL_DEFAULT));
        request.setResponseResult(defaultUrl);
    }
    
    private static boolean isValidateRememberPass(String operatorPass)
    {
        for (int i=0;i<operatorPass.length();i++)
        {
            if (operatorPass.charAt(i) != '●')
                return false;
        }
        return true;
    }
    
    /**
     * 验证操作员密码
     * 
     * @param request       请求对象
     * @param operator      操作员对象
     * @param operatorPass  操作员密码
     * @return              =true表示成功
     * @throws Exception    可能的异常
     */
    public static boolean validatePassword(HttpRequest request, ZmrOperator operator, String operatorPass)
    {
        Asserts.as(operator!=null?null:"操作员对象不能为null");
        Asserts.as(!Validates.isEmptyBlank(operatorPass)?null:"操作员密码不能为空白");
        
        ZmrPassworder passworder = ZmrBootstrap.getPassworder();
        String encodePass = passworder.encode(operator.getOperatorCode(), operatorPass, operator.getOperatorPassSalt());
        return encodePass.equalsIgnoreCase(operator.getOperatorPass());
    }
}
